#ifndef __SCU_SCUBUF_H
#define __SCU_SCUBUF_H

#include "sc.h"

#ifdef __cplusplus
extern "C" {
#endif

#ifndef UINT_FAST8_MAX
#define UINT_FAST8_MAX 255
#endif /* UINT_FAST8_MAX */

#define SCU_BUF_MAX_READERS UINT_FAST8_MAX

#define SCU_BUF_BLOCK_ALL 1
#define SCU_BUF_BLOCK_ANY 2

typedef struct scu_bufptr_s
{
  int ptr, newptr;
} scu_bufptr_t;

typedef int_fast8_t scu_bufptrid_t;
 
struct scu_buf_s;
typedef void (*buf_destructor_t)(struct scu_buf_s *);
typedef struct scu_buf_s
{
  scu_bufptr_t reader[SCU_BUF_MAX_READERS], writer;
  int readers;
  
  uint8_t *data;
  
  int references, finalized, locked, size;
  buf_destructor_t destructor;
} scu_buf_t;

scu_buf_t scuBufferCreate(int size, uint_fast8_t maxreaders,
			  buf_destructor_t destructor);
int scuBufferRemoveReference(scu_buf_t *buf);
int scuBufferFinalize(scu_buf_t *buf);
int scuBufferIsDry(scu_buf_t *buf, scu_bufptrid_t ptr);
scu_bufptrid_t scuBufferAddReader(scu_buf_t *buf);
int scuBufferUnlock(scu_buf_t *buf);
int scuBufferSpaceAvailable(scu_buf_t *buf);
int scuBufferWrite(scu_buf_t *buf, void *data, int size, int options);
int scuBufferDataAvailable(scu_buf_t *buf, scu_bufptrid_t r);
int scuBufferRead(scu_buf_t *buf, scu_bufptrid_t r, void *data, int size,
                  int options);

int  scuBufferAllocate(scu_buf_t *buf, void **data, int size, int options);
void scuBufferReleaseAllocated(scu_buf_t *buf, int size);
int  scuBufferPeek(scu_buf_t *buf, scu_bufptrid_t r, void **data, int size,
                   int options);
void scuBufferReleasePeeked(scu_buf_t *buf, scu_bufptrid_t r, int size);

#ifdef __cplusplus
}
#endif

#endif /* __SCU_BUFFERS_H */
